package com.mybatis.boost.extend.mapper;

import jodd.util.StringUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.env.Environment;

import javax.validation.constraints.NotNull;
import java.lang.annotation.Annotation;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

/**
 * @author jearton
 * @since 2017/2/6
 */
@Data
@NoArgsConstructor
@Slf4j
@ConfigurationProperties(prefix = "mybatis.mapper-scan")
public class MapperScanProperties {

    @NotNull
    private String[] basePackages = {};

    @NotNull
    private Class<?>[] basePackageClasses = {};

    @NotNull
    private Class<? extends Annotation> annotationClass = Mapper.class;

    @NotNull
    private Class<?> markerInterface = Class.class;

    @NotNull
    private Class<? extends MapperFactoryBean> factoryBean = MapperFactoryBean.class;

    @SuppressWarnings("unchecked")
    MapperScanProperties(Environment env) {
        String[] basePackages = env.getProperty("mybatis.mapper-scan.base-packages", String[].class);
        if (basePackages != null) {
            this.basePackages = basePackages;
        }

        String[] basePackageClasses = env.getProperty("mybatis.mapper-scan.base-package-classes", String[].class);
        if (basePackageClasses != null) {
            List<Class<?>> classes = newArrayList();
            try {
                for (String basePackageClass : basePackageClasses) {
                    classes.add(Class.forName(basePackageClass));
                }
            } catch (Exception e) {
                log.error("load basePackageClasses fail", e);
            }
            this.basePackageClasses = classes.stream().toArray(Class[]::new);
        }

        String annotationClass = env.getProperty("mybatis.mapper-scan.annotation-class", String.class);
        if (StringUtil.isNotBlank(annotationClass)) {
            try {
                Class<?> clazz = Class.forName(annotationClass);
                if (Annotation.class.isAssignableFrom(clazz)) {
                    this.annotationClass = (Class<? extends Annotation>) clazz;
                }
            } catch (Exception e) {
                log.error("load annotationClass fail", e);
            }
        }

        String markerInterface = env.getProperty("mybatis.mapper-scan.marker-interface", String.class);
        if (StringUtil.isNotBlank(markerInterface)) {
            try {
                this.markerInterface = Class.forName(markerInterface);
            } catch (Exception e) {
                log.error("load markerInterface fail", e);
            }
        }

        String factoryBean = env.getProperty("mybatis.mapper-scan.factory-bean", String.class);
        if (StringUtil.isNotBlank(factoryBean)) {
            try {
                Class<?> clazz = Class.forName(factoryBean);
                if (MapperFactoryBean.class.isAssignableFrom(clazz)) {
                    this.factoryBean = (Class<? extends MapperFactoryBean>) clazz;
                }
            } catch (Exception e) {
                log.error("load factoryBean fail", e);
            }
        }
    }
}
